﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace UI.Dendrogram
{
    public class Split : Canvas
    {
        #region events
        public event OnBranchUnSelected BranchUnSelected;
        public event OnBranchSelected BranchSelected;
        public event OnBranchExpanded BranchExpanded;
        public event OnBranchCollapsed BranchCollapsed;
        #endregion

        #region settings
        public Orientation Orientation { get; set; }
        public int LeftChildCount { get; set; }
        public int RightChildCount { get; set; }
        public double DistanceFromParent { get; set; }
        public object Data { get; set; }
        public Branch2 LeftBranch { get; set; }
        public Branch2 RightBranch { get; set; }
        public double BranchSpace { get; set; }
        public double DistanceLengthScale { get; set; }
        public Point FromPos { get; set; }
        #endregion

        #region UI
        public Line Header { get; set; }
        public Line LeftShoulder { get; set; }
        public Line RightShoulder { get; set; }
        public Line LeftArm { get; set; }
        public Line RightArm { get; set; }
        public Rect SplitBounds { get; set; }
        public Rectangle Bounds { get; set; }
        private Rect _TreeBounds;
        #endregion

        #region ctor
        public Split(Canvas canvas, Rect treeRect, Orientation orientation, Point startPos,
            int leftChildCount, int rightChildCount, double distanceFromParent,
            object leftData, string leftLabel, object rightData, string rightLabel,
            bool leftIsBranch, bool rightIsBranch, object data, double branchSpace,
            double distanceScale)
        {
            this._TreeBounds = treeRect;
            this.Bounds=new Rectangle();
            this.Orientation = orientation;
            this.FromPos = startPos;
            this.LeftChildCount = leftChildCount;
            this.RightChildCount = rightChildCount;
            this.DistanceFromParent = distanceFromParent;
            this.Data = data;
            this.LeftBranch=new Branch2(leftData,leftLabel,this.FromPos, this.FromPos,leftIsBranch);
            this.RightBranch=new Branch2(rightData,rightLabel,this.FromPos,this.FromPos,rightIsBranch);
            this.BranchSpace = branchSpace;
            this.DistanceLengthScale = distanceScale;

            this.InitializeLayout();

            canvas.Children.Add(this.Bounds);
            this.Bounds.SetValue(Canvas.LeftProperty,_TreeBounds.X);
            this.Bounds.SetValue(Canvas.TopProperty,_TreeBounds.Y);
            this.Bounds.Width = _TreeBounds.Width;
            this.Bounds.Height = _TreeBounds.Height;
            this.Bounds.Fill = new SolidColorBrush(Colors.White);
            canvas.Children.Add(this.Header);
            this.Header.Stroke = new SolidColorBrush(Colors.Green);
            this.Header.StrokeThickness = 2;
            canvas.Children.Add(this.LeftShoulder);
            this.LeftShoulder.Stroke = new SolidColorBrush(Colors.Green);
            this.LeftShoulder.StrokeThickness = 2;
            canvas.Children.Add(this.LeftArm);
            this.LeftArm.Stroke = new SolidColorBrush(Colors.Green);
            this.LeftArm.StrokeThickness = 2;
            canvas.Children.Add(this.RightShoulder);
            this.RightShoulder.Stroke = new SolidColorBrush(Colors.Green);
            this.RightShoulder.StrokeThickness = 2;
            canvas.Children.Add(this.RightArm);
            this.RightArm.Stroke = new SolidColorBrush(Colors.Green);
            this.RightArm.StrokeThickness = 2;
        }
        #endregion

        #region layout
        public void UpdateLayout(Rect treeRect, Point startPos, double branchSpace, double distanceScale)
        {
            this.FromPos = startPos;
            this._TreeBounds = treeRect;
            this.BranchSpace = branchSpace;
            this.DistanceLengthScale = distanceScale;
            this.LeftBranch.FromPos = this.FromPos;
            this.LeftBranch.ToPos = this.FromPos;
            this.RightBranch.FromPos = this.FromPos;
            this.RightBranch.ToPos = this.FromPos;

            this.InitializeLayout();
        }

        private Line InitLine(Point startPos, Point endPos)
        {
            Line line=new Line{X1=startPos.X,Y1=startPos.Y,X2=endPos.X,Y2=endPos.Y};
            line.Width = 2;
            line.Fill = new SolidColorBrush(Colors.Green);
            return line;

        }

        private void InitializeLayout()
        {
            if(this.Orientation==System.Windows.Controls.Orientation.Horizontal)
            {
                Point headerPos=
                    new Point(
                        this.FromPos.X+this.DistanceFromParent *this.DistanceLengthScale,
                        this.FromPos.Y);
                this.Header = this.InitLine(this.FromPos, headerPos);

                double leftArmLen = this.BranchSpace*this.RightChildCount/2;
                Point leftArmPos=new Point(headerPos.X,headerPos.Y-leftArmLen);
                this.LeftBranch.FromPos = leftArmPos;
                this.LeftShoulder = this.InitLine(headerPos, leftArmPos);

                double rightArmLen = this.BranchSpace*this.LeftChildCount/2;
                Point rightArmPos=new Point(headerPos.X,headerPos.Y+rightArmLen);
                this.RightBranch.FromPos = rightArmPos;
                this.RightShoulder = this.InitLine(headerPos, rightArmPos);

                if(this.LeftBranch.ConnectToChildBranch)
                {
                    this.LeftBranch.ToPos = this.LeftBranch.FromPos;
                    this.LeftArm = this.InitLine(this.LeftBranch.FromPos, this.LeftBranch.ToPos);
                }
                else
                {
                    Point leftChildPos = new Point(this._TreeBounds.Height, leftArmPos.Y);
                    this.LeftBranch.ToPos = leftChildPos;
                    this.LeftArm = this.InitLine(this.LeftBranch.FromPos, this.LeftBranch.ToPos);
                }

                if(this.RightBranch.ConnectToChildBranch)
                {
                    this.RightBranch.ToPos = this.RightBranch.FromPos;
                    this.RightArm = this.InitLine(this.RightBranch.FromPos, this.RightBranch.ToPos);
                }
                else
                {
                    Point rightChildPos = new Point(this._TreeBounds.Height, rightArmPos.Y);
                    this.RightBranch.ToPos = rightChildPos;
                    this.RightArm = this.InitLine(this.RightBranch.FromPos, this.RightBranch.ToPos);
                }

                this.SplitBounds=new Rect(
                    headerPos.X,LeftBranch.FromPos.Y,
                    Math.Abs(Math.Max(LeftBranch.ToPos.X,RightBranch.ToPos.X)-headerPos.X),
                    Math.Abs(RightBranch.ToPos.Y-LeftBranch.ToPos.Y));
            }
            else
            {
                Point headerPos=new Point(this.FromPos.X,this.FromPos.Y+this.DistanceFromParent*this.DistanceLengthScale);
                this.Header = this.InitLine(this.FromPos, headerPos);
                double leftArmLen = this.BranchSpace*this.RightChildCount/2;
                Point leftArmPos=new Point(headerPos.X-leftArmLen,headerPos.Y);
                this.LeftBranch.FromPos = leftArmPos;
                this.LeftShoulder = this.InitLine(headerPos, leftArmPos);
                double rightArmLen = this.BranchSpace*this.LeftChildCount/2;
                Point rightArmPos=new Point(headerPos.X+rightArmLen,headerPos.Y);
                this.RightBranch.FromPos = rightArmPos;
                this.RightShoulder = this.InitLine(headerPos, rightArmPos);

                if (this.LeftBranch.ConnectToChildBranch)
                {
                    this.LeftBranch.ToPos = this.LeftBranch.FromPos;
                    this.LeftArm = this.InitLine(this.LeftBranch.FromPos, this.LeftBranch.ToPos);
                }
                else
                {
                    Point leftChildPos = new Point(leftArmPos.X, this._TreeBounds.Height);
                    this.LeftBranch.ToPos = leftChildPos;
                    this.LeftArm = this.InitLine(this.LeftBranch.FromPos, this.LeftBranch.ToPos);
                }

                if (this.RightBranch.ConnectToChildBranch)
                {
                    this.RightBranch.ToPos = this.RightBranch.FromPos;
                    this.RightArm = this.InitLine(this.RightBranch.FromPos, this.RightBranch.ToPos);
                }
                else
                {
                    Point rightChildPos = new Point(rightArmPos.X, this._TreeBounds.Height);
                    this.RightBranch.ToPos = rightChildPos;
                    this.RightArm = this.InitLine(this.RightBranch.FromPos, this.RightBranch.ToPos);
                }

                this.SplitBounds=new Rect(
                    Math.Min(LeftBranch.FromPos.X,RightBranch.FromPos.X),
                    headerPos.Y,
                    Math.Abs(Math.Abs(LeftBranch.ToPos.X-RightBranch.ToPos.X)),
                    Math.Abs(Math.Max(LeftBranch.ToPos.Y,RightBranch.ToPos.Y)-headerPos.Y));
            }
        }

        private void UpdatePositions()
        {
            
        }
        #endregion
    }
}
